// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "electron/shell/browser/execute_command_singleton.h"

#include "base/functional/bind.h"
#include "base/logging.h"
#include "content/public/browser/browser_thread.h"
#include "filemanagement/file_uri/oh_file_uri.h"
#include "ohos/adapter/browser/browser_adapter.h"
#include "shell/browser/browser.h"
#include "shell/browser/window_list.h"

namespace electron {

using namespace ohos::adapter;

// static
ExecuteCommandSingleton* ExecuteCommandSingleton::GetInstance() {
  static base::NoDestructor<ExecuteCommandSingleton> factory;
  return factory.get();
}

void ExecuteCommandSingleton::OnExecute(CommandParameter& param,
                                        std::shared_ptr<CommandResult> result) {
  auto task = [](base::WeakPtr<ExecuteCommandSingleton> executor,
                 const CommandParameter& param,
                 std::shared_ptr<CommandResult> result) {
    do {
      switch (param.type) {
        case CommandType::kNewWindow:
          result->ret_code = 0;
          if (!param.url.empty()) {
            char* path = nullptr;
            auto code = OH_FileUri_GetPathFromUri(param.url.c_str(),
                                                  param.url.length(), &path);
            if (code == FileManagement_ErrCode::ERR_OK) {
              Browser::Get()->OpenFile(path);
              std::free(path);
              path = nullptr;
            } else {
              LOG(ERROR) << "Failed to get path from uri: " << param.url
                         << ", error code: " << code;
              result->ret_code = -1;  // Indicate failure
            }
          }
          break;
        case CommandType::kGetLastActiveWidget:
          result->ret_code = 0;
          result->last_widget_Id = WindowList::GetLastActiveAcceleratedWidget();
          break;
        case CommandType::kAppQuit:
          result->ret_code = 0;
          if (Browser::Get())
            Browser::Get()->Quit();
          break;
        default:
          LOG(ERROR) << "unsupported Operator type:" << (int)param.type;
          break;
      }
    } while (0);

    if (param.is_sync) {
      result->async_callback();
    }
  };

  content::GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE, base::BindOnce(task, AsWeakPtr(), std::move(param), result));
}

void ExecuteCommandSingleton::Register() {
  if (init_for_register_) {
    LOG(WARNING) << "Browser command executor is registered";
    return;
  }

  // Register arkui event
  auto& browser_adapter = BrowserAdapter::GetInstance();
  browser_adapter.RegisterBrowserCallback(
    std::bind(
      &ExecuteCommandSingleton::OnExecute,
      this,
      std::placeholders::_1,
      std::placeholders::_2));

  init_for_register_ = true;
}

base::WeakPtr<ExecuteCommandSingleton> ExecuteCommandSingleton::AsWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

base::WeakPtr<const ExecuteCommandSingleton> ExecuteCommandSingleton::AsWeakPtr() const {
  return weak_factory_.GetWeakPtr();
}

ExecuteCommandSingleton::ExecuteCommandSingleton() = default;

ExecuteCommandSingleton::~ExecuteCommandSingleton() = default;

}  // namespace electron
